package com.xu.chapter;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

/**
 * java8中 农民筛选绿苹果为例
 *
 *  小结  1：行为参数化,就是一个方法接受多个不同的行为作为参数，并在内部使用它，完成不同行为的能力
 *       2：行为参数化可让代码更好的适用不断变化的要求，减少重复代码
 * @author xudenghui
 * @create 2023-04-05 9:03
 **/
public class FilteringApples {

    public static void main(String[] args) {
        List<Apple> inventory = Arrays.asList(new Apple(80,"green"),
                new Apple(155, "green"),
                new Apple(120, "red"));

        //第一次解决方案  筛选绿苹果
        List<Apple> appleList = filterGreenApples(inventory);
        System.out.println(appleList);

        //第二次解决方案  随心筛选某种颜色的苹果
        List<Apple> green = filterAppleByColor(inventory, "green");
        List<Apple> red = filterAppleByColor(inventory, "red");
        System.out.println("绿苹果"+green);
        System.out.println("红苹果"+red);

        //第三次 区分轻苹果 和 重苹果
        List<Apple> apples = filterAppleByWeight(inventory, 150);
        System.out.println("重苹果"+apples);

        /**
         * 如果对大小 形状 颜色 等等属性进行筛选  以及组合筛选 比如绿色的重苹果
         *  考虑把行为作为参数
         *  结论： 多种行为 一个参数
         */
        //根据抽象条件筛选 绿色
        List<Apple> lambdaGreen = filterApples(inventory, (Apple a) -> "green".equals(a.getColor()));
        System.out.println(lambdaGreen);
        //重量
        List<Apple> lambdaWeight = filterApples(inventory, (Apple a) -> a.getWeight() > 150);
        System.out.println(lambdaWeight);
        //组合
        List<Apple> weirdApples = filterApples(inventory, (Apple a) -> a.getWeight() < 80 || "brown".equals(a.getColor()));
        System.out.println(weirdApples);

        /**
         * 再次提升下 变成一个工具类
         * 假如 类型变了 不是Apple了  变成其他的类型了  filterApples就不可用了 任意类型都能用呢
         */
        List<Apple> filterGreen = filter(inventory, (Apple a) -> "green".equals(a.getColor()));
        System.out.println(filterGreen);

    }

    /**
     *  解决方案：1把名字改成filterRedApples 更改if条件来匹配红苹果
     *          2把颜色作为参数传递进去
     * @param inventory
     * @return
     */
    public static List<Apple> filterGreenApples(List<Apple> inventory){
        List<Apple> result = new ArrayList<>();
        for (Apple apple: inventory){
            if ("green".equals(apple.getColor())) {
                result.add(apple);
            }
        }
        return result;
    }

    /**
     * 筛选多种颜色的苹果  浅绿色  暗红色  黄色等
     * @param inventory
     * @param color
     * @return
     */
    public static List<Apple> filterAppleByColor(List<Apple> inventory,String color){
        List<Apple> result = new ArrayList<>();
        for (Apple apple: inventory){
            if (apple.getColor().equals(color)) {
                result.add(apple);
            }
        }
        return result;
    }

    /**
     * 区分轻苹果 和 重苹果
     * @param inventory
     * @param weight
     * @return
     */
    public static List<Apple> filterAppleByWeight(List<Apple> inventory,int weight){
        List<Apple> result = new ArrayList<>();
        for (Apple apple: inventory){
            if (apple.getWeight() > weight) {
                result.add(apple);
            }
        }
        return result;
    }


    /**
     * 行为化参数
     * @param inventory
     * @param p
     * @return
     */
    public static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p){
        List<Apple> result = new ArrayList<>();
        for(Apple apple : inventory){
            if(p.test(apple)){
                result.add(apple);
            }
        }
        return result;
    }

    /**
     * 将List类型抽象化
     */
    public static <T> List<T> filter(List<T> list, Predicate<T> p){
        List<T> result = new ArrayList<>();
        for(T e : list){
            if(p.test(e)){
                result.add(e);
            }
        }
        return result;
    }

    @Data
    @AllArgsConstructor
    @ToString
    public static class Apple {
        private int weight;
        private String color;
    }
}
